package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderService {


    @Value("${ware.url}")
    private String WARE_URL;


    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RabbitService rabbitService;

    /**
     * 保存订单数据
     *
     * @param orderInfo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveOrderInfo(OrderInfo orderInfo) {

//       添加订单数据
        orderInfo.sumTotalAmount();
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        String outTradeNo = "ATGUIGU" + System.currentTimeMillis() + "" + new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        orderInfo.setCreateTime(new Date());
//        设置过期时间
        Calendar calendar = Calendar.getInstance();//获取当前时间
        calendar.add(Calendar.DATE, 1);//当前时间加一天
        orderInfo.setExpireTime(calendar.getTime());
        orderInfo.setTradeBody("");//默认为空
//        获取订单进程
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
//        保存订单表
        orderInfoMapper.insert(orderInfo);
//        获取订单明细表
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
//        保存订单明细表
        for (OrderDetail orderDetail : orderDetailList) {
//            补全订单明细表数据
            orderDetail.setOrderId(orderInfo.getId());
            orderDetailMapper.insert(orderDetail);
        }

//        返回订单编号
        return orderInfo.getId();
    }

    /**
     * 生成流水线订单号
     *
     * @param userId
     * @return
     */
    @Override
    public String getTradeNo(String userId) {
        // 定义key
        String tradeNoKey = "user:" + userId + ":tradeCode";
        // 定义一个流水号
        String tradeNo = UUID.randomUUID().toString().replace("-", "");
        redisTemplate.opsForValue().set(tradeNoKey, tradeNo);
        return tradeNo;
    }

    /**
     * 检测订单号是否与之前一致
     *
     * @param userId      获取缓存中的流水号
     * @param tradeCodeNo 页面传递过来的流水号
     * @return
     */
    @Override
    public boolean checkTradeCode(String userId, String tradeCodeNo) {
        // 定义key
        String tradeNoKey = "user:" + userId + ":tradeCode";
        String redisTradeNo = (String) redisTemplate.opsForValue().get(tradeNoKey);
        return tradeCodeNo.equals(redisTradeNo);
    }

    /**
     * 删除流水线订单号
     *
     * @param userId
     */
    @Override
    public void deleteTradeNo(String userId) {
        // 定义key
        String tradeNoKey = "user:" + userId + ":tradeCode";
        // 删除数据
        redisTemplate.delete(tradeNoKey);

    }

    /**
     * 验证库存
     *
     * @param skuId
     * @param skuNum
     * @return
     */
    @Override
    public boolean checkStock(Long skuId, Integer skuNum) {
        // 远程调用http://localhost:9001/hasStock?skuId=10221&num=2
        String result = HttpClientUtil.doGet(WARE_URL + "/hasStock?skuId=" + skuId + "&num=" + skuNum);
//       返回true有库存
        return "1".equals(result);
    }



    /**
     * 根据订单id更该订单状态
     * @param orderId
     */
    @Override
    public  void updateOrderStatusList(Long orderId,ProcessStatus processStatus) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(orderId);
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfo.setProcessStatus(processStatus.name());
        orderInfoMapper.updateById(orderInfo);
    }

    /**
     * 根据订单id更该订单状态
     * @param orderId
     */
    @Override
    public void updateOrderStatus(Long orderId) {
        updateOrderStatusList(orderId,ProcessStatus.CLOSED);

//        关闭交易记录,发送订单id进行关闭
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE, MqConst.ROUTING_PAYMENT_CLOSE, orderId);
    }

    /**
     * 根据订单id获取订单信息
     * @param orderId
     * @return
     */
    @Override
    public OrderInfo getOrderInfo(Long orderId) {
//        查询订单
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
//        查询订单明细表
        QueryWrapper<OrderDetail> wrapper  = new QueryWrapper<>();
        wrapper.eq("order_id",orderId);
        List<OrderDetail> orderDetailList = orderDetailMapper.selectList(wrapper);
        orderInfo.setOrderDetailList(orderDetailList);
        return orderInfo;
    }

    /**
     *更改订单状态减库存
     * @param orderId
     */
    @Override
    public void sendOrderStatus(Long orderId) {
//        修改订单状态
        updateOrderStatusList(orderId,ProcessStatus.NOTIFIED_WARE);
//        通知仓库减库存
        OrderInfo orderInfo = getOrderInfo(orderId);
//        转orderInfo转化为map在转json数据返回
        Map map = initJsonMap(orderInfo);

        String wareJson = JSON.toJSONString(map);

//        发送消息减少库存
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK, MqConst.ROUTING_WARE_STOCK, wareJson);

    }

//        转orderInfo转化为map在转json数据返回
    public  Map initJsonMap(OrderInfo orderInfo) {
//        封装orderInfo数据
        Map<String,Object> map = new HashMap<>();
        map.put("orderId", orderInfo.getId());
        map.put("consignee", orderInfo.getConsignee());
        map.put("consigneeTel", orderInfo.getConsigneeTel());
        map.put("orderComment", orderInfo.getOrderComment());
        map.put("orderBody", orderInfo.getTradeBody());
        map.put("deliveryAddress", orderInfo.getDeliveryAddress());
        map.put("paymentWay", "2");//支付方式在线支付
//        map.put("wareId", orderInfo.getWareId());// 仓库Id ，减库存拆单时需要使用！

//        获取orderInfoDetial数据
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();

//        封装orderDetail数据返回
        List<Map<String, Object>> mapList = orderDetailList.stream().map(orderDetail -> {
            Map<String, Object> orderDetailMap = new HashMap<>();
            orderDetailMap.put("", orderDetail.getId());
            return orderDetailMap;
        }).collect(Collectors.toList());

        map.put("details", orderDetailList);
        return map;
    }

    /**
     *        根据数据拆分订单
     * @param orderId
     * @param wareSkuMap
     * @return
     */
    @Override
    public List<OrderInfo> orderSplitOrder(String orderId, String wareSkuMap) {

//        拆分订单书记总合
        List<OrderInfo> orderInfoArrayList = new ArrayList<>();

//            获取原来订单数据
        OrderInfo originOrderInfo = getOrderInfo(Long.valueOf(orderId));
//        wareSkuMap:  [{"wareId":"1","skuIds":["2","10"]},{"wareId":"2","skuIds":["3"]}]
        List<Map> mapList = JSON.parseArray(wareSkuMap, Map.class);
        if (!CollectionUtils.isEmpty(mapList)){
            for (Map map : mapList) {
//            获取订单id
                String wareId = (String) map.get("wareId");
                //获取skuIds
                List<String> skuIds = (List<String>) map.get("skuIds");

//                创建订单集合封装数据
                OrderInfo subOrderInfo = new OrderInfo();
                BeanUtils.copyProperties(originOrderInfo,subOrderInfo);
//                复制其他数据
                subOrderInfo.setId(null);
//                设置父id的数据
                subOrderInfo.setParentOrderId(Long.valueOf(orderId));
//                赋值库存
                    subOrderInfo.setWareId(wareId);

                    //存储订单集合
                List<OrderDetail> orderDetailList = new ArrayList<>();
//                匹配对应的数据
                for (String skuId : skuIds) {
                    for (OrderDetail orderDetail : originOrderInfo.getOrderDetailList()) {
                        if (Long.valueOf(skuId)==orderDetail.getSkuId()){
//                            赋值订单明细表数据
                            orderDetailList.add(orderDetail);
                        }
                    }
                }
//                赋值订单消息表
                originOrderInfo.setOrderDetailList(orderDetailList);
//            计算总的金额
                subOrderInfo.sumTotalAmount();
//                保存订单数据
                saveOrderInfo(subOrderInfo);

//                封装订单数据
                orderInfoArrayList.add(subOrderInfo);
            }
        }
        return orderInfoArrayList;
    }

    /**
     * 关闭支付和订单状态
     * @param orderId
     * @param flag
     */
    @Override
    public void updateOrderStatus(Long orderId, String flag) {

//        更改订单状态
        updateOrderStatusList(orderId,ProcessStatus.CLOSED);

        if ("2".equals(flag)){
            //        关闭交易记录,发送订单id进行关闭,更改订单和支付
            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE, MqConst.ROUTING_PAYMENT_CLOSE, orderId);
        }

    }
}
